-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Conversation
what about some methods to handle binary data? base64 encode/decode basically |
9badff4
to
9d0411d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks solid to me. I'm good with merging it.
Rebase Needed |
07f18ac
to
998c00f
Compare
Voight Kampff Integration Test Succeeded (Results) |
38de5f6
to
b3a4bf9
Compare
Voight Kampff Integration Test Succeeded (Results) |
Voight Kampff Integration Test Failed (Results) |
b3a4bf9
to
aa40a3f
Compare
Voight Kampff Integration Test Succeeded (Results) |
aa40a3f
to
dd202ff
Compare
Voight Kampff Integration Test Succeeded (Results) |
return wrapper | ||
|
||
methods = [a for a in get_non_properties(self) | ||
if hasattr(a, '__name__')] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
None of my decorated methods seem to have a __name__
attribute. However they do get assigned the api_method
.
Example Skill with an API method: https://github.com/krisgesling/skill-api-source-skill
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I get True
If I do self.log.info(hasattr(self.speak_from_other_skill, '__name__'))
on your skill
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The check does look a bit wonky though. Let's see if I can improve it...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, same if I log from the Skill itself, but logging from here returns False:
if self.skill_id == 'skill-api-source-skill':
for a in get_non_properties(self):
LOG.info("{} has __name__: {}".format(a, hasattr(a, '__name__')))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahh, the get_non_properties() returns a string not a reference to the attribute, so looks like we need this to be:
methods = [a for a in get_non_properties(self)
if hasattr(getattr(self, a), '__name__')]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah great catch...how has this ever worked?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pushed your suggested fix and updated the CLI code to handle :api without a skill argument. Gonna rebase this and fix the conflict, then I'll see if I can re-verify the functionality
dd202ff
to
6f5f2ff
Compare
6f5f2ff
to
b3d4202
Compare
Rebased and fixed the conflict |
Voight Kampff Integration Test Succeeded (Results) |
Hey, this is working well now. Have you thought much about what some unit tests for this might look like? Also, I just did tiny edit of the top comment to fix a typo in the example code. |
Haven't thought too much about it but I think I can write up a small suite of tests for it. |
The skill api allows skills to define a public api which can easily be accessed by other skills over the message bus just as easy as working with a normal object. The skill api object is generated from the skill's public_api property. It's a dict where each key is turned into a method on the api object. The method is defined as "api_method": { "type": message type string "func": handler method "help": help string for cli } Example skill: class Test2(MycroftSkill): def __init__(self): MycroftSkill.__init__(self) self.public_api = { 'speak': { 'type': 't2.speak', 'func': self.handle_speak, 'help': 'speak the test sentence\nand another line\n\nlast' }, 'speak2': { 'type': 't2.speak2', 'func': self.handle_speak2, 'help': 'speak the other sentence' } } def handle_speak(self, message): self.speak('This is a test') self.bus.emit(message.response(data=None)) def handle_speak2(self, message): self.speak('This is another test') self.bus.emit(message.response(data=None))
The api methods are now much easier to use, almost transparent. The current caveat is that only "standarad" python types are acceptable (int, float, str, list, bool, None) due to the json serialization. - api methods are now created with the skill_api_method decorator - both arguments and keyword arguments are sent to the api method instead of the message object - api methods now uses a normal return statement instead of having to handle creating response messages on the bus. For example if the datetime skill wants to make the datetime string fetchable simply add the skill_api_method decorator to the get_display_date method. @skill_api_method def get_display_date(self, day=None, location=None): """Returns the date and time as a string.""" [...] The methods return value will be sent back to the caller and can be used from a skill through datetime = SkillApi.get('mycroft-date-time.mycroftai') self.log.info(datetime.get_display_date())
b3d4202
to
0ccc0f2
Compare
Rebased and fixed conflict and added unittests for the key components. |
Voight Kampff Integration Test Succeeded (Results) |
- Tests for the MycroftSkill side implementation - Tests for the generated SkillApi objects
0ccc0f2
to
5685259
Compare
Voight Kampff Integration Test Succeeded (Results) |
hello will the skills api be added to pycroft soon? |
Hey @Touhey - if you switch to the dev channel and pull the latest changes, this will now be available :D We'll also be releasing the next major version of mycroft-core in a few weeks. Then it will be available on the stable / master branch |
hi thanks for speedy reply where can i find the dev channel for picroft? |
@Touhey - this is the dev channel of mycroft-core so if you SSH into the device, or hook up a keyboard and monitor - the following should work:
|
Description
This is a suggestion for an easy way for skills to publish and use other skills shared methods. The idea is that for example the alarm skill wants to
The skill api object is generated from the skill's public_api property. It's a dict where each key is turned into a method on the api object. The method is defined as
This dict is generated from methods in the skill tagged with the
skill_api_method
decorator.Example skill:
To use this skill from another skill
import the SkillApi class
and then get an api object and use that to trigger the skill:
This also adds a help interface to the api in the CLI,
:api SKILL
will list available api methods.Contributor license agreement signed?
CLA [ Yes ]